home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / mxutil / tspak17 / do_rec.asm < prev    next >
Assembly Source File  |  1994-07-26  |  11KB  |  473 lines

  1. ; DO_REC.ASM
  2. ;
  3. ; External assembler subroutine for Recwav.pas, performs the actual record-
  4. ; ing of sound.  Although this is to be assembled to an .obj file, it is
  5. ; almost a .com file in its own right.  This routine assumes the DAC has
  6. ; already been initialized.
  7. ;
  8.  
  9. CODE        SEGMENT    BYTE PUBLIC
  10.         ASSUME    CS:CODE,DS:CODE
  11.         PUBLIC    DO_REC
  12. DO_REC      PROC    NEAR
  13.         JMP    START
  14.         ;
  15.         ; Stack frame structure.
  16.         ;
  17. STACKFRAME    STRUC    [BP]
  18. OLDBP        DW    ?    ; caller's BP
  19. RETADDR        DW    ?    ; return address
  20. ASCZFILE    DD    ?    ; pointer to ASCIIZ filename of output file
  21. BUFFER1         DD      ?       ; pointer to DMA buffer 1
  22. BUFFER0         DD      ?       ; pointer to DMA buffer 0
  23. INRATE        DW    ?    ; input sampling rate in Hz, for .wav header
  24. DIVIDER        DW    ?    ; divider for Int 1Ah function 82h
  25.         ENDS
  26.         ;
  27.         ; Return codes.
  28.         ;
  29. RECOK        EQU    0    ; recording successful
  30. DISKERR        EQU    1    ; disk I/O error
  31. FULLDISK    EQU    2    ; disk full
  32. OVERFLOW    EQU    3    ; input overflow (sampling rate too fast)
  33. OPENFAIL    EQU    4    ; open failed on output file
  34. WORKING        EQU    5    ; sound input in progress (not a return code)
  35.         ;
  36.         ; Local data.  First, copies of parameters (easier to get at,
  37.         ; particularly from inside an interrupt handler).
  38.         ;
  39. ASCZFILE_L    DD    0    ; local copy of parameter ASCZFILE
  40. BUFFERPTRS    LABEL    DWORD    ; buffer pointers, as array[0..1] of dword
  41. BUFFER0_L    DD    0    ; local copy of parameter BUFFER0
  42. BUFFER1_L    DD    0    ; local copy of parameter BUFFER1
  43. DIVIDER_L    DW    0    ; local copy of parameter DIVIDER
  44. EVENT        DW    WORKING    ; event status (return code)
  45. CURRENTOUT    DW    0    ; current output buffer (0 or 1)
  46. CURRENTIN    DW    0    ; current input buffer (0 or 1)
  47. FULLBUFFER    DB    0,0    ; buffer full flags, 1 = full
  48. LASTBUFFER    DB    0,0    ; last buffer flags, 1 = final buffer
  49. STOPNOW        DB    0    ; 1 = recording should stop
  50. RECSTOPPED    DB    0    ; 1 = sound recording stopped
  51. KEYPRESSED    DB    0    ; key pressed flag, 1 = key has been pressed
  52. HANDLE        DW    0    ; file handle of output file
  53. FILELEN        DD    0    ; length of the output file
  54. STARTPROMPT    DB    "Press a key to begin recording.",0Dh,0Ah,"$"
  55. STOPPROMPT    DB    "Press a key to stop recording.",0Dh,0Ah,"$"
  56. INT15VEC    DD    0    ; default Int 15h vector
  57.         ;
  58.         ; RIFF WAVE header template, for writing to the output file.
  59.         ; 44 bytes long.  OUTRATE1 and OUTRATE2 should be filled in
  60.         ; before the template is written out.  After recording is
  61.         ; done, the dword at offset 4 should be filled in with the
  62.         ; length of the output file minus 8, and the dword at offset
  63.         ; 40 should be filled in with the length of the output file
  64.         ; minus 44.
  65.         ;
  66. TEMPLATE    LABEL    BYTE
  67.         DB    'RIFF'    ; RIFF header
  68. RIFFSIZE    DD    0    ; (length of output file) - 8 goes here
  69.         DB    'WAVEfmt '    ; WAVE header and format chunk label
  70.         DD    16    ; format chunk length
  71.         DW    1    ; Microsoft PCM format tag
  72.         DW    1    ; mono
  73. OUTRATE1    DW    0    ; fill in with sampling rate
  74.         DW    0
  75. OUTRATE2    DW    0    ; fill in sampling rate here too
  76.         DW    0
  77.         DW    1    ; bytes per sample
  78.         DW    8    ; bits per sample
  79.         DB    'data'
  80. DATASIZE    DD    0    ; (length of output file) - 44 goes here
  81.         ;
  82.         ; Replacement Int 15h handler.  This is actually 2 Int 15h
  83.         ; handlers in one:  the first part handles Int 15h function
  84.         ; 4Fh, the keyboard intercept, setting the KEYPRESSED flag
  85.         ; above and telling the BIOS to ignore the keystroke; the
  86.         ; second part handles Int 15h, AX=91FBh, the BIOS callout
  87.         ; for sound chip DMA EOP.
  88.         ;
  89.         ; First part:  keyboard intercept.  Set KEYPRESSED flag (if
  90.         ; it's a make code) and tell the BIOS to ignore the keystroke.
  91.         ;
  92. INT15HDLR:    CMP    AH,4Fh
  93.         JNE    I15_NOTKEY
  94.         NOT    AL        ; 1 in bit 7 = make code
  95.         ROL    AL,1        ; 1 in bit 0 = make code
  96.         AND    AL,1        ; zero out other bits
  97.         OR    CS:KEYPRESSED,AL    ; set if make code
  98.         CLC
  99.         RETF    2
  100.         ;
  101.         ; If not keyboard intercept, and not DMA EOP, then jump to
  102.         ; default handler.
  103.         ;
  104. I15_NOTKEY:    CMP    AX,91FBh
  105.         JE    I15_DMAEOP
  106.         JMP    DWORD PTR CS:INT15VEC
  107.         ;
  108.         ; DMA end-of-process occurred on sound input.  DS addresses
  109.         ; local data.
  110.         ;
  111. I15_DMAEOP:    PUSH    AX
  112.         PUSH    BX
  113.         PUSH    CX
  114.         PUSH    DX
  115.         PUSH    DS
  116.         PUSH    ES
  117.         PUSH    CS
  118.         POP    DS
  119.         ;
  120.         ; Check first if STOPNOW flag is set; if so, stop.  (The main
  121.         ; program sets this flag in case of disk errors.)
  122.         ;
  123.         CMP    STOPNOW,1
  124.         JNE    NOTSTOPNOW
  125.         MOV    RECSTOPPED,1
  126.         JMP    I15_END
  127.         ;
  128.         ; STOPNOW flag not set.  Mark the current buffer full.  If a 
  129.         ; keystroke has occurred, mark the current buffer last and 
  130.         ; stop.
  131.         ;
  132. NOTSTOPNOW:    MOV    BX,CURRENTIN
  133.         MOV    FULLBUFFER[BX],1
  134.         CMP    KEYPRESSED,1
  135.         JNE    NOKEYYET
  136.         MOV    RECSTOPPED,1
  137.         MOV    LASTBUFFER[BX],1
  138.         JMP    I15_END
  139.         ;
  140.         ; No keypress yet.  Switch input buffers.
  141.         ;
  142. NOKEYYET:    XOR    BX,1
  143.         MOV    CURRENTIN,BX
  144.         ;
  145.         ; If the new current input buffer is still marked full,
  146.         ; overflow has occurred.
  147.         ;
  148.         CMP    FULLBUFFER[BX],1
  149.         JNE    NOOVERFLOW
  150.         MOV    RECSTOPPED,1
  151.         MOV    EVENT,OVERFLOW
  152.         JMP    I15_END
  153.         ;
  154.         ; Buffer is empty.  Fill it.
  155.         ;
  156. NOOVERFLOW:    MOV    AH,82h
  157.         SHL    BX,1
  158.         SHL    BX,1
  159.         LES    BX,BUFFERPTRS[BX]
  160.         MOV    CX,32768
  161.         MOV    DX,DIVIDER_L
  162.         INT    1Ah
  163. I15_END:    POP    ES
  164.         POP    DS
  165.         POP    DX
  166.         POP    CX
  167.         POP    BX
  168.         POP    AX
  169.         IRET
  170.         ;
  171.         ; Subroutine, opens the output file.  Returns:  carry set if
  172.         ; error, file handle in AX otherwise.
  173.         ;
  174. OPENFILE:    PUSH    CX
  175.         PUSH    DX
  176.         PUSH    DS
  177.         MOV    AH,3Ch
  178.         XOR    CX,CX
  179.         LDS    DX,ASCZFILE_L
  180.         INT    21h
  181.         POP    DS
  182.         POP    DX
  183.         POP    CX
  184.         RET
  185.         ;
  186.         ; Subroutine, closes the output file and flushes the disk
  187.         ; buffers.  Returns nothing.
  188.         ;
  189. CLOSEFILE:    PUSH    AX
  190.         PUSH    BX
  191.         MOV    AH,3Eh
  192.         MOV    BX,HANDLE
  193.         INT    21h
  194.         MOV    AH,0Dh
  195.         INT    21h
  196.         POP    BX
  197.         POP    AX
  198.         RET
  199.         ;
  200.         ; Subroutine, erases the output file.
  201.         ;
  202. ERASEFILE:    PUSH    AX
  203.         PUSH    DX
  204.         PUSH    DS
  205.         MOV    AH,41h
  206.         LDS    DX,ASCZFILE_L
  207.         INT    21h
  208.         POP    DS
  209.         POP    DX
  210.         POP    AX
  211.         RET
  212.         ;
  213.         ; Subroutine, starts sound recording.
  214.         ;
  215. STARTRECORD:    PUSH    AX
  216.         PUSH    BX
  217.         PUSH    CX
  218.         PUSH    DX
  219.         PUSH    ES
  220.         MOV    AH,82h
  221.         LES    BX,BUFFER0_L
  222.         MOV    CX,32768
  223.         MOV    DX,DIVIDER_L
  224.         INT    1Ah
  225.         POP    ES
  226.         POP    DX
  227.         POP    CX
  228.         POP    BX
  229.         POP    AX
  230.         RET
  231.         ;
  232.         ; Subroutine, stops sound recording.  Waits for the recording
  233.         ; process to indicate that it has stopped.
  234.         ;
  235. STOPRECORD:    MOV    STOPNOW,1
  236. L0:        CMP    RECSTOPPED,1
  237.         JNE    L0
  238.         RET
  239.         ;
  240.         ; Main routine.  BP addresses the stack frame; DS addresses
  241.         ; the code segment.
  242.         ;
  243. START:        PUSH    BP
  244.         MOV    BP,SP
  245.         PUSH    DS
  246.         PUSH    CS
  247.         POP    DS
  248.         ;
  249.         ; Create local copies of parameters.
  250.         ;
  251.         MOV    AX,DIVIDER
  252.         MOV    DIVIDER_L,AX
  253.         MOV    AX,INRATE        ; fill in header template
  254.         MOV    OUTRATE1,AX
  255.         MOV    OUTRATE2,AX
  256.         LES    AX,BUFFER0
  257.         MOV    WORD PTR BUFFER0_L,AX
  258.         MOV    WORD PTR BUFFER0_L+2,ES
  259.         LES    AX,BUFFER1
  260.         MOV    WORD PTR BUFFER1_L,AX
  261.         MOV    WORD PTR BUFFER1_L+2,ES
  262.         LES    AX,ASCZFILE
  263.         MOV    WORD PTR ASCZFILE_L,AX
  264.         MOV    WORD PTR ASCZFILE_L+2,ES
  265.         ;
  266.         ; Open the output file.
  267.         ;
  268.         CALL    OPENFILE
  269.         JNC    OPEN_SUCCESS
  270.         ;
  271.         ; Open failed.  Set event code and jump to end.
  272.         ;
  273.         MOV    EVENT,OPENFAIL
  274.         JMP    MAIN_EXIT
  275.         ;
  276.         ; Open succeeded.  Save handle and write .wav header.
  277.         ;
  278. OPEN_SUCCESS:    MOV    HANDLE,AX
  279.         MOV    BX,AX
  280.         MOV    AH,40h
  281.         MOV    CX,44
  282.         MOV    DX,OFFSET TEMPLATE
  283.         INT    21h
  284.         JC    HDR_FAIL
  285.         CMP    AX,CX
  286.         JE    HDR_SUCCESS
  287.         ;
  288.         ; Error writing to disk.  Close the output file and delete it,
  289.         ; set event code to DISKERR, and jump to exit.
  290.         ;
  291. HDR_FAIL:    CALL    CLOSEFILE
  292.         CALL    ERASEFILE
  293.         MOV    EVENT,DISKERR
  294.         JMP    MAIN_EXIT
  295.         ;
  296.         ; Header successfully written out.  Display starting prompt
  297.         ; to the user.
  298.         ;
  299. HDR_SUCCESS:    MOV    AH,9
  300.         MOV    DX,OFFSET STARTPROMPT
  301.         INT    21h
  302.         ;
  303.         ; Flush the keyboard buffer.
  304.         ;
  305. KEYBUF_FLUSH:    MOV    AH,1
  306.         INT    16h
  307.         JZ    KEYBUF_EMPTY
  308.         MOV    AH,0
  309.         INT    16h
  310.         JMP    KEYBUF_FLUSH
  311.         ;
  312.         ; Keyboard buffer empty.  Wait for a keystroke.
  313.         ;
  314. KEYBUF_EMPTY:    MOV    AH,0
  315.         INT    16h
  316.         ;
  317.         ; Display stopping prompt to the user.
  318.         ;
  319.         MOV    AH,9
  320.         MOV    DX,OFFSET STOPPROMPT
  321.         INT    21h
  322.         ;
  323.         ; Hook Int 15h.
  324.         ;
  325.         MOV    AX,3515h
  326.         INT    21h
  327.         MOV    WORD PTR INT15VEC,BX
  328.         MOV    WORD PTR INT15VEC+2,ES
  329.         MOV    AX,2515h
  330.         MOV    DX,OFFSET INT15HDLR
  331.         INT    21h
  332.         ;
  333.         ; Start recording.
  334.         ;
  335.         CALL    STARTRECORD
  336.         ;
  337.         ; **** Main output loop.  If overflow has occurred, close
  338.         ; and delete the output file and exit the program.
  339.         ;
  340. MAINLOOP:    CMP    EVENT,OVERFLOW
  341.         JNE    NO_OVERFLOW
  342.         CALL    CLOSEFILE
  343.         CALL    ERASEFILE
  344.         JMP    UNHOOK
  345.         ;
  346.         ; No overflow.  See if the current output buffer is full yet.
  347.         ; If not, keep checking for overflow or a full buffer.
  348.         ;
  349. NO_OVERFLOW:    MOV    SI,CURRENTOUT
  350.         CMP    FULLBUFFER[SI],1
  351.         JNE    MAINLOOP
  352.         ;
  353.         ; Write the buffer to disk.
  354.         ;
  355.         PUSH    DS
  356.         MOV    AH,40h
  357.         MOV    BX,HANDLE
  358.         MOV    CX,32768
  359.         SHL    SI,1
  360.         SHL    SI,1
  361.         LDS    DX,BUFFERPTRS[SI]
  362.         INT    21h
  363.         POP    DS
  364.         ;
  365.         ; If disk error, stop recording, close and delete the output 
  366.         ; file, set the return code to DISKERR, and exit.
  367.         ;
  368.         JNC    BUFFERDONE
  369.         CALL    STOPRECORD
  370.         CALL    CLOSEFILE
  371.         CALL    ERASEFILE
  372.         MOV    EVENT,DISKERR
  373.         JMP    UNHOOK
  374.         ;
  375.         ; If full disk, stop recording, set return code to FULLDISK, 
  376.         ; and go set the file size in the .wav header.
  377.         ;
  378. BUFFERDONE:    CMP    AX,CX
  379.         JE    NOTFULL
  380.         CALL    STOPRECORD
  381.         MOV    EVENT,FULLDISK
  382.         JMP    SETSIZE
  383.         ;
  384.         ; Disk not full.  If this was the last output buffer, exit
  385.         ; the loop (recording already stopped).
  386.         ;
  387. NOTFULL:    MOV    BX,CURRENTOUT
  388.         CMP    LASTBUFFER[BX],1
  389.         JE    MAIN_LPEND
  390.         ;
  391.         ; Not the last output buffer.  Mark the current output buffer
  392.         ; empty, switch buffers, and go to the top of the loop to wait 
  393.         ; for more output.
  394.         ;
  395.         MOV    FULLBUFFER[BX],0
  396.         XOR    CURRENTOUT,1
  397.         JMP    MAINLOOP
  398.                 ;
  399.                 ; Recording successful.
  400.                 ;
  401. MAIN_LPEND:    MOV    EVENT,RECOK
  402.         ;
  403.         ; Set the size fields in the .wav header.  First, get the 
  404.         ; length of the file from DOS.
  405.         ;
  406. SETSIZE:    MOV    AX,4202h
  407.         MOV    BX,HANDLE
  408.         XOR    CX,CX
  409.         MOV    DX,CX
  410.         INT    21h
  411.         JC    SIZEERROR
  412.         ;
  413.         ; Fill in the size fields in the .wav header template.
  414.         ;
  415.         SUB    AX,8
  416.         SBB    DX,0
  417.         MOV    WORD PTR RIFFSIZE,AX
  418.         MOV    WORD PTR RIFFSIZE+2,DX
  419.         SUB    AX,36
  420.         SBB    DX,0
  421.         MOV    WORD PTR DATASIZE,AX
  422.         MOV    WORD PTR DATASIZE+2,DX
  423.         ;
  424.         ; Seek to the beginning of the file and write out the header
  425.         ; template again.
  426.         ;
  427.         MOV    AX,4200h
  428.         MOV    BX,HANDLE
  429.         XOR    CX,CX
  430.         MOV    DX,CX
  431.         INT    21h
  432.         JC    SIZEERROR
  433.         MOV    AH,40h
  434.         MOV    BX,HANDLE
  435.         MOV    CX,44
  436.         MOV    DX,OFFSET TEMPLATE
  437.         INT    21h
  438.         JC    SIZEERROR
  439.         CMP    AX,CX
  440.         JNE    SIZEERROR
  441.         ;
  442.         ; Close the output file and exit.
  443.         ;
  444.         CALL    CLOSEFILE
  445.         JMP    UNHOOK
  446.         ;
  447.         ; File error occurred while setting the size fields in the
  448.         ; .wav header, or when closing the file.  Close the file
  449.         ; (if not closed already) and delete it, then set the return
  450.         ; code to DISKERR.
  451.         ;
  452. SIZEERROR:    CALL    CLOSEFILE
  453.         CALL    ERASEFILE
  454.         MOV    EVENT,DISKERR
  455.         ;
  456.         ; Unhook Int 15h.
  457.         ;
  458. UNHOOK:        PUSH    DS
  459.         MOV    AX,2515h
  460.         LDS    DX,INT15VEC
  461.         INT    21h
  462.         POP    DS
  463.         ;
  464.         ; Set return code, restore registers and exit.
  465.         ;
  466. MAIN_EXIT:    MOV    AX,EVENT
  467.         POP    DS
  468.         POP    BP
  469.         RET    16    ; discard parameters
  470. DO_REC          ENDP
  471. CODE        ENDS
  472.         END
  473.